#include "kbd.h"
#include "stdlib.h"
#include "platform.h"
#include "core.h"
#include "keyboard.h"
#include "conf.h"
#include "action_stack.h"
#include "camera.h"
#include "histogram.h"
#include "gui_lang.h"
#include "console.h"
#include "lang.h"
#include "gui_lang.h"
#include "gui_osd.h"
#include "gui_draw.h"

long kbd_last_clicked;
int state_kbd_script_run;
int kbd_blocked;
static long delay_target_ticks;
static int soft_half_press = 0;
static int key_pressed;

// ------ add by Masuji SUTO (start) --------------
static int mvideo,mplay;
static int nSW=0;
static int nRmt=0;
static int nWt=0;
static int nCount=0;
static int nCa=0;
static int nCount2=0;
static int nTxvideo=0;
static int nTxzoom=0;
static int nTxzname=KEY_ZOOM_IN;
static int nPlyname=KEY_LEFT;
static int nIntzpos;
static int nReczoom=0;
static int nTxtblcr=0;
int shutter_int=0;

extern int new_meas;
extern EXPO_TYPE expo;

#if defined(CAMERA_ixus960_sd950)
static int nFirst=1;
#endif

#if defined(CAMERA_a450) || defined(CAMERA_ixus50_sd400) || defined(CAMERA_ixusizoom_sd30) || defined(CAMERA_ixus40_sd300) || defined(CAMERA_ixus55_sd450) || defined(CAMERA_ixus60_sd600) || defined(CAMERA_ixus65_sd630) || defined(CAMERA_ixus70_sd1000) || defined(CAMERA_ixus700_sd500) || defined(CAMERA_ixus750_sd550) || defined(CAMERA_ixus850_sd800) || defined(CAMERA_ixus900_sd900) || defined(CAMERA_ixus75_sd750) || defined(CAMERA_a470) || defined(CAMERA_ixus90_sd790) || defined(CAMERA_ixus100_sd780) || defined(CAMERA_ixus120_sd940) || defined(CAMERA_a480) || defined(CAMERA_d10) || defined(CAMERA_ixus85_sd770) || defined(CAMERA_ixus95_sd1200) || defined(CAMERA_a495)
#define ZSTEP_TABLE_SIZE 7
static int nTxtbl[]={0,1,2,3,4,5,6};
#endif

#if defined(CAMERA_s2is) || defined(CAMERA_s3is) || defined(CAMERA_s5is) || defined(CAMERA_sx10) || defined(CAMERA_sx1)|| defined(CAMERA_sx20)
#define ZSTEP_TABLE_SIZE 8
static int nTxtbl[]={0,11,25,41,64,86,105,128};
#endif

#if defined(CAMERA_sx30)
#define ZSTEP_TABLE_SIZE 11
static int nTxtbl[]={0,20,40,60,80,100,120,140,160,180,200};
#endif

#if defined(CAMERA_tx1)
#define ZSTEP_TABLE_SIZE 8
static int nTxtbl[]={0,18,43,55,76,93,113,124};
#endif

#if defined(CAMERA_a430) || defined(CAMERA_a460) || defined(CAMERA_a530) || defined (CAMERA_a540) || defined(CAMERA_a550) || defined(CAMERA_a560) || defined(CAMERA_a570) || defined(CAMERA_a590) ||defined(CAMERA_ixus860_sd870) || defined(CAMERA_ixus960_sd950) || defined(CAMERA_ixus80_sd1100) || defined(CAMERA_ixus970_sd890) || defined(CAMERA_ixus980_sd990)
#define ZSTEP_TABLE_SIZE 8
static int nTxtbl[]={0,1,2,3,4,5,6,7};
#endif


#if defined(CAMERA_a610) ||  defined(CAMERA_a620) || defined(CAMERA_a630) || defined(CAMERA_a640) || defined(CAMERA_ixus800_sd700) || defined(CAMERA_ixus950_sd850)
#define ZSTEP_TABLE_SIZE 9
static int nTxtbl[]={0,1,2,3,4,5,6,7,8};
#endif

#if defined (CAMERA_a700) || defined(CAMERA_a710) || defined (CAMERA_a720) || defined (CAMERA_a2000) 
#define ZSTEP_TABLE_SIZE 8
static int nTxtbl[]={0,2,4,6,8,10,12,14};
#endif

#if defined(CAMERA_a650) || defined(CAMERA_g7) || defined(CAMERA_g9)
#define ZSTEP_TABLE_SIZE 8
static int nTxtbl[]={0,2,4,6,8,10,12,13};
#endif
// ------ add by Masuji SUTO (end)   --------------
#if defined(CAMERA_sx100is) || defined(CAMERA_sx110is) || defined(CAMERA_sx120is)
#define ZSTEP_TABLE_SIZE 8
static int nTxtbl[]={0,3,6,9,13,16,20,23};
#endif

#if defined(CAMERA_ixus870_sd880)
#define ZSTEP_TABLE_SIZE 10
static int nTxtbl[]={0,1,2,3,4,5,6,7,8,9};
#endif

#if defined(CAMERA_sx200is)
#define ZSTEP_TABLE_SIZE 7
static int nTxtbl[]={0,16,32,62,78,102,125};
#endif

#if defined(CAMERA_g11) || defined(CAMERA_g12)
#define ZSTEP_TABLE_SIZE 14
static int nTxtbl[]={0,1,2,3,4,5,6,7,8,9,10,11,12,13};
#endif

#if defined(CAMERA_s90) || defined(CAMERA_s95)
#define ZSTEP_TABLE_SIZE 10
static int nTxtbl[]={0,1,2,3,4,5,6,7,8,9};
#endif

#ifdef OPT_SCRIPTING
// remote autostart
void script_autostart()
{
    kbd_blocked = 1;
    gui_kbd_enter();
    console_clear(); 
    script_console_add_line("***Autostart***"); //lang_str(LANG_CONSOLE_TEXT_STARTED));
    script_start_gui( 1 );
}
#endif

void enter_alt()
{
    kbd_key_release_all();          
    kbd_blocked = 1;
    gui_kbd_enter();
}


void exit_alt()
{
    kbd_blocked = 0;
    gui_kbd_leave();
}

// ------ add by Masuji SUTO (start) --------------
void set_key_press(int nSet)
{
	key_pressed = nSet;
	kbd_blocked = nSet;
	nRmt = nSet;
}
// ------ add by Masuji SUTO (end) --------------

/*------------------- Alex scriptless remote additions start --------------------*/
static int remoteHalfShutter=0, remoteFullShutter=0, remoteShooting=0, remoteClickTimer=0, remote_script_start_ready=0;
#define REMOTE_MAX_CLICK_LENGTH	50
/*-------------------- Alex scriptless remote additions end ---------------------*/

extern unsigned char *img_copy;
extern short sel_frame_blink;

#pragma pack(1)
struct TGAHeader
{
    unsigned char  identsize;          // size of ID field that follows 18 byte header (0 usually)
    unsigned char  colourmaptype;      // type of colour map 0=none, 1=has palette
    unsigned char  imagetype;          // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed

    unsigned short colourmapstart;     // first colour map entry in palette
    unsigned short colourmaplength;    // number of colours in palette
    unsigned char  colourmapbits;      // number of bits per palette entry 15,16,24,32

    unsigned short xstart;             // image x origin
    unsigned short ystart;             // image y origin
    unsigned short width;              // image width in pixels
    unsigned short height;             // image height in pixels
    unsigned char  bits;               // image bits per pixel 8,16,24,32
    unsigned char  descriptor;         // image descriptor bits (vh flip bits)
};
#pragma pack()

static struct TGAHeader tga_header = {
    0,
    0,
    3,
    0, 0, 0,
    0, 0, 360, 240,
    8,
    1<<5
};

static struct TGAHeader tga_header2 = {
    0,
    1,
    1,
    0, 256, 24,
    0, 0, 360, 240,
    8,
    1<<5
};

static unsigned char tga_footer[] = { "\0\0\0\0\0\0\0\0TRUEVISION-XFILE.\0" };

unsigned char tga_colormap[256*3];

extern unsigned long meas_time;


/* 
    main kb processing
*/
long kbd_process()
{
/* Alternative keyboard mode stated/exited by pressing print key.
 * While running Alt. mode shoot key will start a script execution.
 */
    static int nCER=0;
// ------ modif by Masuji SUTO (start) --------------


    // deals with alt-mode switch and delay emulation
    if (key_pressed)
    {
        if (kbd_is_key_pressed(conf.alt_mode_button)
                || ((key_pressed >= CAM_EMUL_KEYPRESS_DELAY)
                && (key_pressed < CAM_EMUL_KEYPRESS_DELAY+CAM_EMUL_KEYPRESS_DURATION))) {
            if (key_pressed <= CAM_EMUL_KEYPRESS_DELAY+CAM_EMUL_KEYPRESS_DURATION) 
                key_pressed++;
            if (key_pressed == CAM_EMUL_KEYPRESS_DELAY) 
                kbd_key_press(conf.alt_mode_button);
            else if (key_pressed == +CAM_EMUL_KEYPRESS_DELAY+CAM_EMUL_KEYPRESS_DURATION) 
                kbd_key_release(conf.alt_mode_button);
            return 1;
        } else if (kbd_get_pressed_key() == 0) {
            if (key_pressed != 100 && (key_pressed < CAM_EMUL_KEYPRESS_DELAY)) {
                kbd_blocked = 1-kbd_blocked;
                if (kbd_blocked) 
                    gui_kbd_enter();
                else
                    gui_kbd_leave();
            }
            key_pressed = 0;
            return 1;
        }
        return 1;
    }
       
    if (kbd_is_key_pressed(conf.alt_mode_button))
    {
        key_pressed = 1;
        kbd_key_release_all();          
        return 1;
    }
    
    if (kbd_blocked) //Alt
    {
        action_stack_process_all();
        
        
        if (gui_get_mode() == GUI_MODE_ALT)
        {
            if (kbd_is_key_pressed(KEY_SHOOT_FULL))
            {
                kbd_key_release(KEY_SHOOT_FULL);
                return 1;
            }

            if (kbd_is_key_clicked(KEY_PRINT))
            {
                if (((mode_get()&MODE_MASK) == MODE_REC))
                {
                    short mmode;
                    get_property_case(PROPCASE_METERING_MODE, &mmode, sizeof(mmode));
                    
                    mmode = (mmode+1) % 3;
                    set_property_case(PROPCASE_METERING_MODE, &mmode, sizeof(mmode));
                    
                    //shooting_set_nd_filter_state (mmode > 0, 1);
                
                    return 1;
                }
                else
                    return 0;
            }

        
//            if (kbd_use_up_down_left_right_as_fast_switch())
  //              return 1;
                
            if (kbd_is_key_clicked(KEY_ZOOM_IN) || kbd_is_key_clicked(KEY_ZOOM_OUT))
            {
                int m=mode_get(); 

                if (conf.fast_ev && (m&MODE_MASK) == MODE_REC && (m&MODE_SHOOTING_MASK) == MODE_P)
                {
                    if (kbd_is_key_clicked(KEY_ZOOM_IN))
                    {
                        shooting_set_prop(PROPCASE_EV_CORRECTION_1,shooting_get_prop(PROPCASE_EV_CORRECTION_1)+(conf.fast_ev_step+1)*16);
                        shooting_set_prop(PROPCASE_EV_CORRECTION_2,shooting_get_prop(PROPCASE_EV_CORRECTION_2)+(conf.fast_ev_step+1)*16);
                    }
                    else
                    {
                        shooting_set_prop(PROPCASE_EV_CORRECTION_1,shooting_get_prop(PROPCASE_EV_CORRECTION_1)-(conf.fast_ev_step+1)*16);
                        shooting_set_prop(PROPCASE_EV_CORRECTION_2,shooting_get_prop(PROPCASE_EV_CORRECTION_2)-(conf.fast_ev_step+1)*16);
                    }
                
                    return 1;
                }
                else
                    return 0;
            }
                
            if (conf.save_frame_info)
            {
                if (kbd_is_key_clicked(KEY_UP))
                {
                    if (sel_aind > min_aind)
                    {
                        sel_aind--;
                        //draw_restore();
                    }
                    
                    return 1;
                }
        
                if (kbd_is_key_clicked(KEY_DOWN))
                {
                    if (sel_aind < max_aind)
                    {
                        sel_aind++;
                        //draw_restore();
                    }
                    
                    return 1;
                }
                
                if (kbd_is_key_clicked(KEY_LEFT))
                {
                    if (conf.sel_frame > 1 && !sel_frame_blink)
                    {
                        conf.sel_frame--;
                        conf_save();
                    }
                
                    return 1;
                }
    
                if (kbd_is_key_clicked(KEY_RIGHT))
                {
                    if (conf.sel_frame < 12 && !sel_frame_blink)
                    {
                        conf.sel_frame++;
                        conf_save();
                    }
    
                    return 1;
                }                
            
            
            
                static int key_pressed2 = 0;
                if (key_pressed2)
                {
                    if (kbd_is_key_pressed(KEY_SET)
                        || ((key_pressed2 >= CAM_EMUL_KEYPRESS_DELAY)
                        && (key_pressed2 < CAM_EMUL_KEYPRESS_DELAY+CAM_EMUL_KEYPRESS_DURATION)))
                    {
                        if (key_pressed2 <= CAM_EMUL_KEYPRESS_DELAY+CAM_EMUL_KEYPRESS_DURATION) 
                            key_pressed2++;
            /*            if (key_pressed2 == CAM_EMUL_KEYPRESS_DELAY) 
                            kbd_key_press(KEY_LEFT);
                    else*/
                        if (key_pressed2 == CAM_EMUL_KEYPRESS_DELAY+CAM_EMUL_KEYPRESS_DURATION)
                        {
                            if (img_copy && !sel_frame_blink)
                            {
                                static char buf[100];                                    
                                static struct tm tm;
                                FILE *f;
            
                                memcpy(&tm, localtime(&meas_time), sizeof(struct tm));
                
                                sprintf(buf, "A/LOG/%02d.%02d", tm.tm_mday, tm.tm_mon+1);
                                mkdir(buf);
                                
                                sprintf(buf, "A/LOG/%02d.%02d/%02d.%02d-%02d-osd.tga", tm.tm_mday, tm.tm_mon+1, tm.tm_hour, tm.tm_min, conf.sel_frame);
                                f = fopen(buf, "w+b");
                                if (f)
                                {
                                    fwrite(&tga_header2, 1, sizeof(tga_header), f);
                                    fwrite(&tga_colormap, 1, sizeof(tga_colormap), f);
                                    fwrite(frame_buffer[0], 1, screen_buffer_width*screen_buffer_height, f);
                                    fwrite(&tga_footer, 1, sizeof(tga_footer), f);
                                    fclose(f);
                                }
                                
                                sprintf(buf, "A/LOG/%02d.%02d/%02d.%02d-%02d-img.tga", tm.tm_mday, tm.tm_mon+1, tm.tm_hour, tm.tm_min, conf.sel_frame);
                                f = fopen(buf, "w+b");
                                if (f)
                                {
                                    fwrite(&tga_header, 1, sizeof(tga_header), f);
                                    fwrite(img_copy, 1, vid_get_viewport_height() * vid_get_viewport_buffer_width(), f);
                                    fwrite(&tga_footer, 1, sizeof(tga_footer), f);
                                    fclose(f);
                                }
                                
                                sel_frame_blink = 15;
                            }
    
                            kbd_key_release_all();    
                        }
                        return 1;
                    }
                    else
                        key_pressed2 = 0;
    
                    return 1;
                }

                if (kbd_is_key_pressed(KEY_SET))
                {

                    key_pressed2 = 1;
                    kbd_key_release_all();    
                    return 1;
                }
            } //conf.save_frame_info
            else
            {
                if (kbd_is_key_clicked(KEY_DOWN))
                {
                    expo.ev96_measured_prev1 = 0;
                    expo.ev96_measured_prev2 = 0;

                    kbd_key_release_all();    
                    return 1;
                }                

                static int kkk = 1;
                if (kbd_is_key_pressed(KEY_SET))
                {
                    if (kkk)
                    {
                        conf.expo_type = !conf.expo_type;
                        kkk = 0;
                    }   

                    kbd_key_release_all();    
                    return 1;
                }
                else
                    kkk = 1;
            }
      
            static int allow_new_meas = 0;
            if (kbd_is_key_pressed(KEY_SHOOT_HALF))
            {
                /*if (allow_new_meas)
                {
                    new_meas = 1;
                    allow_new_meas = 0;
                }*/
                //kbd_key_release_all();
                //kbd_key_press(KEY_SHOOT_HALF);
                return 0;
            }
            /*else
            {
                allow_new_meas = 1;
            }*/
            
        }
        
        gui_kbd_process();
    }
    else //Normal
    {
        other_kbd_process(); // processed other keys in not <alt> mode 
    }

    return kbd_blocked;
}

int kbd_is_blocked() {
	return kbd_blocked;
}

void kbd_set_block(int bEnableBlock) {
    kbd_blocked = bEnableBlock ? 1 : 0;
}

/*long kbd_use_up_down_left_right_as_fast_switch() {
    static long key_pressed = 0; // ??? static masking a global
    int m=mode_get(); 
    int jogdial;
    
    if (!)
        return 0;

    if (!(kbd_is_key_pressed(KEY_ZOOM_IN)) && !(kbd_is_key_pressed(KEY_ZOOM_OUT))) key_pressed = 0;

#if !CAM_HAS_JOGDIAL
    if (kbd_is_key_pressed(KEY_ZOOM_IN)) {
        if (key_pressed == 0) {
            shooting_set_prop(PROPCASE_EV_CORRECTION_1,shooting_get_prop(PROPCASE_EV_CORRECTION_1)+(conf.fast_ev_step+1)*16);
            shooting_set_prop(PROPCASE_EV_CORRECTION_2,shooting_get_prop(PROPCASE_EV_CORRECTION_2)+(conf.fast_ev_step+1)*16);
            //EnterToCompensationEVF();
            key_pressed = KEY_ZOOM_IN;
        }

        kbd_key_release_all();        
        return 1;
    } 

    if (kbd_is_key_pressed(KEY_ZOOM_OUT)) {
        if (key_pressed == 0) {
            shooting_set_prop(PROPCASE_EV_CORRECTION_1,shooting_get_prop(PROPCASE_EV_CORRECTION_1)-(conf.fast_ev_step+1)*16);
            shooting_set_prop(PROPCASE_EV_CORRECTION_2,shooting_get_prop(PROPCASE_EV_CORRECTION_2)-(conf.fast_ev_step+1)*16);
            //EnterToCompensationEVF();
            key_pressed = KEY_ZOOM_OUT;
        }
        
        kbd_key_release_all();
        return 1;
    } 
#else
    jogdial=get_jogdial_direction();

    if (conf.fast_ev &&kbd_is_key_pressed(KEY_SHOOT_HALF) && (jogdial==JOGDIAL_RIGHT) && ((m&MODE_SHOOTING_MASK) != MODE_M) && !mode_video) {
            shooting_set_prop(PROPCASE_EV_CORRECTION_1,shooting_get_prop(PROPCASE_EV_CORRECTION_1)+(conf.fast_ev_step+1)*16);
            shooting_set_prop(PROPCASE_EV_CORRECTION_2,shooting_get_prop(PROPCASE_EV_CORRECTION_2)+(conf.fast_ev_step+1)*16);
            EnterToCompensationEVF();
        }

    if (conf.fast_ev &&kbd_is_key_pressed(KEY_SHOOT_HALF) && (jogdial==JOGDIAL_LEFT) && ((m&MODE_SHOOTING_MASK) != MODE_M) && !mode_video) {
            shooting_set_prop(PROPCASE_EV_CORRECTION_1,shooting_get_prop(PROPCASE_EV_CORRECTION_1)-(conf.fast_ev_step+1)*16);
            shooting_set_prop(PROPCASE_EV_CORRECTION_2,shooting_get_prop(PROPCASE_EV_CORRECTION_2)-(conf.fast_ev_step+1)*16);
            EnterToCompensationEVF();
        }
#endif

    return 0;
}*/
